package libnetdb.dm.assoc.base;

import java.util.*;

public class ExtendedChiSquare 
        implements RuleIndex, IndexBuilder {
    
    private Litemset givenSet = null;

    static{
        IndexManager manager = IndexManager.getInstance();
        manager.register(new ExtendedChiSquare());
    }

    public ExtendedChiSquare(){        
    }
    
    public String getName() {
        return "ExtendedChiSquare";
    }

    public String getTitle() {
        return "Extended Chi Square";
    }
    
    public RuleIndex createIndex(){
        return new ExtendedChiSquare();
    }
    
    public Litemset getGivenSet(){
        return givenSet;
    }

    public double getIndex(Rule rule) {
        Litemset cause = rule.getCause();
        Litemset conse = rule.getConsequence();
        RuleSet ruleSet = rule.getRuleSet();
        Iterator it = ruleSet.decensterIterator(cause);
        double minValue = rule.getChiSquare();
        Litemset localGiven = null; 
        while(it.hasNext()){
            Litemset given = (Litemset) it.next();
            double all = given.count, a = cause.count,
                    b = ruleSet.getCount(conse.merge(given)),
                    ab = rule.getItems().count, x = a * b / all; 
            double tmp = chi(ab, x) + chi(b - ab, b - x) + 
                    chi(a - ab, a - x) + 
                    chi(all - a - b + ab, all - a - b + x);
            if(tmp < minValue){
                minValue = tmp;
                localGiven = given;
            }
        }
        this.givenSet = localGiven;
        return minValue; 
    } 

    private static double chi(double a, double b){
        return b > 1E-5 ? (a - b) * (a - b) / b : 0.0;
    }
    
}
